package wxwork

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/gin/log"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/wxwork/wxbizjsonmsgcrypt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type WxApp struct {
	Corpid         string
	AgentId        string
	Secret         string
	Token          string
	EncodingAESKey string
}

// const token = "4roHZDG47LwQrz9s"
// const receiverId = "ww6c523376a74c38c1"
// const encodingAeskey = "ahwfiL8x9nVo8a7JbolYb8IkIKmhvvxEcJUAInvlquj"

func GetTicket(accessToken string) string {
	url := "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=" + accessToken + "&type=agent_config"
	method := "GET"

	client := http.Client{
		Timeout: 300 * time.Second,
	}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
		return ""
	}
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	return string(body)
}
func GetTicketV2(accessToken string) string {
	url := "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=" + accessToken
	method := "GET"

	client := http.Client{
		Timeout: 300 * time.Second,
	}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
		return ""
	}
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	return string(body)
}
func getString(str, endstr string, start int, msg *string) int {
	end := strings.Index(str, endstr)
	*msg = str[start:end]
	return end + len(endstr)
}

func VerifyURL(r *http.Request, app WxApp) string {
	//httpstr := `&{GET /?msg_signature=825075c093249d5a60967fe4a613cae93146636b&timestamp=1597998748&nonce=1597483820&echostr=neLB8CftccHiz19tluVb%2BUBnUVMT3xpUMZU8qvDdD17eH8XfEsbPYC%2FkJyPsZOOc6GdsCeu8jSIa2noSJ%2Fez2w%3D%3D HTTP/1.1 1 1 map[Cache-Control:[no-cache] Accept:[*/*] Pragma:[no-cache] User-Agent:[Mozilla/4.0]] 0x86c180 0 [] false 100.108.211.112:8893 map[] map[] <nil> map[] 100.108.79.233:59663 /?msg_signature=825075c093249d5a60967fe4a613cae93146636b&timestamp=1597998748&nonce=1597483820&echostr=neLB8CftccHiz19tluVb%2BUBnUVMT3xpUMZU8qvDdD17eH8XfEsbPYC%2FkJyPsZOOc6GdsCeu8jSIa2noSJ%2Fez2w%3D%3D <nil>}`
	fmt.Println(r, r.Body)
	httpstr := r.URL.RawQuery
	start := strings.Index(httpstr, "msg_signature=")
	start += len("msg_signature=")

	var msg_signature string
	next := getString(httpstr, "&timestamp=", start, &msg_signature)

	var timestamp string
	next = getString(httpstr, "&nonce=", next, &timestamp)

	var nonce string
	next = getString(httpstr, "&echostr=", next, &nonce)

	echostr := httpstr[next:]

	echostr, _ = url.QueryUnescape(echostr)
	fmt.Println(msg_signature, timestamp, nonce, echostr, next)

	wxcpt := wxbizjsonmsgcrypt.NewWXBizMsgCrypt(app.Token, app.EncodingAESKey, app.Corpid, wxbizjsonmsgcrypt.XmlType)
	echoStr, cryptErr := wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr)
	if nil != cryptErr {
		log.Info("verifyUrl fail", cryptErr)
	}
	fmt.Println("verifyUrl success echoStr", string(echoStr))
	return string(echoStr)

}

type MsgContent struct {
	ToUsername   string `xml:"ToUserName"`
	FromUsername string `xml:"FromUserName"`
	CreateTime   uint32 `xml:"CreateTime"`
	MsgType      string `xml:"MsgType"`
	Content      string `xml:"Content"`
	Msgid        string `xml:"MsgId"`
	AgentId      string `xml:"AgentID"`
	Event        string `xml:"Event"`
	EventKey     string `xml:"EventKey"`
}

func MsgHandler(r *http.Request, app WxApp) (MsgContent, string) {
	httpstr := r.URL.RawQuery
	start := strings.Index(httpstr, "msg_signature=")
	start += len("msg_signature=")

	var msg_signature string
	next := getString(httpstr, "&timestamp=", start, &msg_signature)

	var timestamp string
	next = getString(httpstr, "&nonce=", next, &timestamp)

	nonce := httpstr[next:]
	log.Info(msg_signature, timestamp, nonce)
	body, err := ioutil.ReadAll(r.Body)

	wxcpt := wxbizjsonmsgcrypt.NewWXBizMsgCrypt(app.Token, app.EncodingAESKey, app.Corpid, wxbizjsonmsgcrypt.XmlType)

	msg, Crypterr := wxcpt.DecryptMsg(msg_signature, timestamp, nonce, body)
	log.Info(string(msg))
	log.Info(Crypterr)
	var msgContent MsgContent
	err = xml.Unmarshal(msg, &msgContent)
	if nil != err {
		log.Info("Unmarshal fail", err)
	}
	log.Info(msgContent, err)
	ToUsername := msgContent.ToUsername
	msgContent.ToUsername = msgContent.FromUsername
	msgContent.FromUsername = ToUsername
	msgContent.AgentId = app.AgentId
	replayJson, err := json.Marshal(&msgContent)
	log.Info(msgContent, string(replayJson))
	encryptMsg, cryptErr := wxcpt.EncryptMsg(string(replayJson), timestamp, nonce)
	if nil != cryptErr {
		log.Info("DecryptMsg fail", string(replayJson))
	}
	sEncryptMsg := string(encryptMsg)
	log.Info("after encrypt sEncryptMsg", sEncryptMsg)
	return msgContent, string(msg)
}

func CallbackHandler(r *http.Request, app WxApp) (MsgContent, string) {
	httpstr := r.URL.RawQuery
	var msgContent MsgContent
	echo := strings.Index(httpstr, "echostr")
	if echo != -1 {
		httpstr = VerifyURL(r, app)
	} else {
		msgContent, httpstr = MsgHandler(r, app)
	}

	return msgContent, httpstr
}
